#!/usr/bin/python
# vim: fdm=marker fmr={{{,}}} cms=#%s

import os
import sys
import re
import string

SOAR=os.environ.get('SOAR')
if not SOAR: SOAR='/opt/soar'
sys.path.append(SOAR+'/common/python')
try:
    from soar import *
except ImportError:
    print >>sys.stderr, """\
Import soar fail 
%s
%s
""" % (sys.exc_value, sys.version)
    sys.exit(1)

def usage(selfname):
#{{{
    print "Usage: %s TABLE" % selfname
#}}}

def extract_table(table, sql):
#{{{
    res=re.search('create table %s ?\((.*?)\);' % table, sql)
    if not res:
        print "Error: no create table syntax"
        return None
    cols=re.split(',', res.group(1))
    tabdef=[]
    for idx in range(len(cols)):
        arr=re.split(' +', cols[idx])
        res=re.match('(.*?)\((.*?)\)', arr[1])
        if res:
            type=res.group(1)
            size=int(res.group(2))
        else:
            type=arr[1]
            size=0
        tabdef.append({'name':arr[0], 'type':type.lower(), 'size':size})
    return tabdef
#}}}

def extract_primary_key(table, sql):
#{{{
    res=re.search('create unique index %s_x00 on %s ?\((.*?)\);' % (table, table), sql)
    if not res:
        print "Error: no create unique index x00 syntax"
        return None
    cols=re.split(',', res.group(1))
    pkdef=[]
    for col in cols:
        pkdef.append(col.lower())
    return pkdef
#}}}

def gen_include(SVCENV_DIR, table, tabdef):
#{{{
    file=open(SVCENV_DIR+'/src/include/dbstruct/%s.h' % table, 'w')

    print >>file, '''\
#ifndef __DBSTRUCT_%s__
#define __DBSTRUCT_%s__

__BEGIN_DECLS

struct %s
{
''' % (table.upper(), table.upper(), table)

    for col in tabdef:
        if col['type'] in ('char', 'varchar'):
            print >>file, "    char     %s[%d+1];" % (col['name'], col['size'])
        elif col['type'] == 'int':
            print >>file, "    int      %s;" % col['name']
        elif col['type'] == 'smallint':
            print >>file, "    short    %s;" % col['name']
        elif col['type'] == 'timestamp':
            print >>file, "    char     %s[30+1];" % col['name']
        else:
            print "Error: %s %s invalid" % (col['name'], col['type'])
            return 1
    print >>file, '''\
};
extern int dbs_%s(MYSQLC db, char *operation, struct %s *%s);
''' % (table, table, table)

    print >>file, '''\
__END_DECLS

#endif'''

    file.close()

    print "Generate include file succeed"
#}}}

def gen_auto(SVCENV_DIR, table, tabdef, pkdef):
#{{{
    file=open(SVCENV_DIR+'/src/db/auto/%s.c' % table, 'w')

    file.write('''\
#include <soar.h>
#include <dbstruct/%s.h>

int dbs_%s(MYSQLC db, char *operation, struct %s *%s)
{
    char sql[BUFFER_SIZE];
    int res;

    if(strcasecmp(operation, "INIT") == 0)
    {
''' % (table, table, table, table))
    for col in tabdef:
        if col['type'] in ('char', 'varchar'):
            file.write('''\
        strcpy(%s->%s, SPACES);
''' % (table, col['name']))
        elif col['type'] in ('int', 'smallint'):
            file.write('''\
        %s->%s=0;
''' % (table, col['name']))
        elif col['type'] == 'timestamp':
            file.write('''\
        strcpy(%s->%s, "19700101000000");
''' % (table, col['name']))
    file.write('''\
        return(MY_OK);
    }
''')

    file.write('''\
    else if(strcasecmp(operation, "INSERT") == 0)
    {
        sprintf(sql, 
            "insert into %s values("
''' % table)
    for col in tabdef:
        if col['type'] in ('char', 'varchar', 'timestamp'):
            file.write('''\
            "\'%s\'''')
        elif col['type'] in ('int', 'smallint'):
            file.write('''\
            "%d''')
        if tabdef.index(col) < len(tabdef)-1:
            file.write(',')
        file.write('"\n')
    file.write('''\
            ")",
''')
    for col in tabdef:
        file.write('''\
            %s->%s''' % (table, col['name']))
        if tabdef.index(col) < len(tabdef)-1:
            file.write(',')
        file.write('\n')
    file.write('''\
            );
        res=mysqlc_exec_ex(db, sql);
        return(res);
    }
''')

    file.write('''\
    else if(strcasecmp(operation, "DELETE") == 0)
    {
        sprintf(sql, 
            "delete from %s where "
''' % table)
    for col in pkdef:
        file.write('''\
            "%s=%%s''' % (col))
        if pkdef.index(col) < len(pkdef)-1:
            file.write(' and ')
        file.write('"\n')
    file.write('''\
            ,
''')
    for col in pkdef:
        file.write('''\
            %s->%s''' % (table, col))
        if pkdef.index(col) < len(pkdef)-1:
            file.write(',')
        file.write('\n')
    file.write('''\
            );
        res=mysqlc_exec_ex(db, sql);
        return(res);
    }
''')

    file.write('''\
    else if(strcasecmp(operation, "SELECT") == 0)
    {
        struct dbc_rset rset;

        sprintf(sql, 
            "select * from %s where " 
''' % table)
    for col in pkdef:
        file.write('''\
            "%s=%%s''' % (col))
        if pkdef.index(col) < len(pkdef)-1:
            file.write(' and ')
        file.write('"\n')
    file.write('''\
            ,
''')
    for col in pkdef:
        file.write('''\
            %s->%s''' % (table, col))
        if pkdef.index(col) < len(pkdef)-1:
            file.write(',')
        file.write('\n')
    file.write('''\
            );
        res=mysqlc_query_ex(db, sql, 1, &rset);
        if(res != MY_OK)
            return(res);
''')
    for col in tabdef:
        if col['type'] in ('char', 'varchar', 'timestamp'):
            file.write('''\
        dbc_col_export_char(&rset, 0, %d, %s->%s);
''' % (tabdef.index(col), table, col['name']))
        elif col['type'] in ('int', 'smallint'):
            file.write('''\
        %s->%s=dbc_col_export_int(&rset, 0, %d);
''' % (table, col['name'], tabdef.index(col)))
    file.write('''\
        dbc_query_free(&rset);
''')
    file.write('''\
        return(MY_OK);
    }
''')

    file.write('''\
    return(RET_ERR_PARA);
}
''')

    file.close()

    cmd='cd %s/src/db/auto; gcc -Wall -g -I%s/src/include -I%s/common/c/include -c %s.c -o %s.o' % (SVCENV_DIR, SVCENV_DIR, SOAR, table, table)
    res=os.system(cmd)
    if res:
        print 'Error: compile auto file fail'
        return 1
    cmd='cd %s/src/db/auto; ar -crl %s/lib/libdbauto.a %s.o' % (SVCENV_DIR, SVCENV_DIR, table)
    res=os.system(cmd) 
    if res:
        print 'Error: ar auto file fail'
        return 1

    print "Generate auto file succeed"
#}}}

def main(argc, argv):
#{{{
    if argc < 2:
        usage(os.path.basename(argv[0]))
        return 1
    table=argv[1]

    SVCENV_DIR=os.environ.get('SVCENV_DIR')
    if not SVCENV_DIR:
        print "Error: SVCENV_DIR not set"
        return 1

    table=table.lower();
    sql='';
    file=open(table+'.sql', 'r')
    for line in map(string.strip, file.readlines()):
        sql=sql+line
    file.close()

    sql=re.sub('\t', ' ', sql)
    sql=re.sub(' {2,}', ' ', sql)
    #print sql

    tabdef=extract_table(table, sql)
    if not tabdef:
        return 1

    pkdef=extract_primary_key(table, sql)
    if not pkdef:
        return 1

    res=gen_include(SVCENV_DIR, table, tabdef)
    if res:
        return 1

    res=gen_auto(SVCENV_DIR, table, tabdef, pkdef)
    if res:
        return 1
#}}}

if __name__ == '__main__':
    main(len(sys.argv), sys.argv)
